<template>
	<div class="animated bounceInDown sele_none">
		<el-row>
			<el-col :span="24">
				<div class="separate_page">
					<h3>用户统计</h3>
					<div v-loading="memberLoading" element-loading-background="rgba(255, 255, 255, 0.8)"
						class="dflex animated bounceInDown">
						<div class="tag">
							<i class="iconfont iconguanli_zongyonghu"></i>
							<div>
								<div class="tag_title">总用户数</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.member_cnt">
								</v-countup>
							</div>
						</div>
						<div class="tag">
							<i class="iconfont iconjin7tian"></i>
							<div>
								<div class="tag_title">近7天新增量</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.member_cnt_7">
								</v-countup>
							</div>
						</div>
						<div class="tag">
							<i class="iconfont iconzuori"></i>
							<div>
								<div class="tag_title">昨日新增量</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.member_cnt_yesterday">
								</v-countup>
							</div>
						</div>
						<div class="tag">
							<i class="iconfont iconjinri"></i>
							<div>
								<div class="tag_title">今日新增量</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.member_cnt_today">
								</v-countup>
							</div>
						</div>
						<div class="tag">
							<i class="iconfont iconpay"></i>
							<div>
								<div class="tag_title">今日付款数</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.pay_cnt"></v-countup>
							</div>
						</div>
						<div class="tag">
							<i class="iconfont iconxiaofei1"></i>
							<div>
								<div class="tag_title">今日总消费</div>
								<v-countup class="tag_data" start-value="0" :end-value="memberSta.pay_money"
									:decimals="2"></v-countup>
							</div>
						</div>
					</div>
				</div>
			</el-col>
		</el-row>
		<el-row :gutter="16">
			<el-col :span="14">
				<div class="separate_page area2">
					<div class="dflex_sb">
						<h3>日/月新增数</h3>
						<div>
							<el-button class="echarts-btn" size="mini" :class="{ active: memberCutBtn == '日' }"
								@click="memberDay" round>日</el-button>
							<el-button class="echarts-btn" size="mini" :class="{ active: memberCutBtn == '月' }"
								@click="memberMonth" round>月</el-button>
						</div>
					</div>
					<div id="member" class="h100"></div>
				</div>
			</el-col>
			<el-col :span="10">
				<div class="separate_page area2">
					<h3>用户/性别 分布</h3>
					<div id="memberDist" class="h100"></div>
				</div>
			</el-col>
		</el-row>
		<el-row>
			<el-col :span="24">
				<div class="separate_page margin_b_0 area3">
					<h3>用户省份分布</h3>
					<div id="memberGeo" class="h100 animated bounceInDown"></div>
				</div>
			</el-col>
		</el-row>
		<el-backtop target="uni-page-body"></el-backtop>
	</div>
</template>

<script>
	import vCountup from 'vue-countupjs';
	import echarts from 'echarts';
	import china from 'echarts/map/json/china.json';
	echarts.registerMap('china', china);
	export default {
		components: {
			vCountup
		},
		data() {
			return {
				memberLoading: false,
				memberSta: {
					member_cnt: 0,
					member_cnt_7: 0,
					member_cnt_yesterday: 0,
					member_cnt_today: 0,
					pay_cnt: 0,
					pay_money: 0
				},
				memberCutBtn: '日',
				memberDom: null,
				memberOption: [],
				memberDistDom: null,
				memberDistOption: [],
				mapData: [],
				memberGeoDom: null,
				memberGeoOption: []
			};
		},
		methods: {
			async getMember() {
				this.memberLoading = true;
				const res1 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id')
					})
					.groupBy('all')
					.groupField('count(*) as member_cnt')
					.get();

				const $ = this.$db.$cmd.aggregate;
				let today = new Date();
				today.setTime(today.getTime() - 24 * 60 * 60 * 1000 * 7);
				const res2 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id'),
						create_time: $.gt(today.getTime())
					})
					.groupBy('all')
					.groupField('count(*) as member_cnt_7')
					.get();

				today = new Date();
				today.setTime(today.getTime() - 24 * 60 * 60 * 1000);
				const res3 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id'),
						yy_mm_dd: today.format('yyyy年MM月dd日')
					})
					.groupBy('all')
					.groupField('count(*) as member_cnt_yesterday')
					.get();

				today = new Date();
				const res4 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id'),
						yy_mm_dd: today.format('yyyy年MM月dd日')
					})
					.groupBy('all')
					.groupField('count(*) as member_cnt_today')
					.get();

				const res5 = this.$db['wmzmall-order']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id'),
						yy_mm_dd: today.format('yyyy年MM月dd日'),
						order_pay_state: '已付款'
					})
					.groupBy('all')
					.groupField('count(*) as pay_cnt, sum(order_actural_paid) as pay_money')
					.get();

				await Promise.all([res1, res2, res3, res4, res5])
					.then(res => {
						this.memberSta = {
							...this.memberSta,
							...res[0].result.data[0],
							...res[1].result.data[0],
							...res[2].result.data[0],
							...res[3].result.data[0],
							...res[4].result.data[0]
						};
					})
					.catch(err => {
						this.memberLoading = false;
					});

				this.memberLoading = false;

				this.memberSta.pay_money = this.memberSta.pay_money / 100;
			},
			async memberDay() {
				this.memberCutBtn = '日';

				uni.setStorage({
					key: '__memberCutSta' + this.$route.path,
					data: this.memberCutBtn
				});

				this.memberDom.showLoading({
					text: '加载中 · · ·',
					color: '#ff6a6c',
					textColor: '#000',
					maskColor: 'rgba(255, 255, 255, 1)'
				});

				const res1 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id')
					})
					.groupBy('dateToString(add(new Date(0),create_time),"%Y年%m月%d日","+0800") as time')
					.groupField('count(*) as cnt')
					.orderBy('time desc')
					.limit(30)
					.get();

				let res = {
					code: 0,
					datas: []
				};

				await Promise.all([res1]).then(resData => {
					res.datas = resData[0].result.data || [];
				}).catch(err => {
					close("err", err)
					this.memberDom.hideLoading();
				});

				this.memberDom.hideLoading();

				this.memberOption.xAxis.data = [];
				this.memberOption.series[0].data = [];

				let today;
				let todaystr;
				for (let i = 30; i >= 0; i--) {
					today = new Date();
					today.setTime(today.getTime() - 1000 * 60 * 60 * 24 * i);
					todaystr = today.format('yyyy年MM月dd日');

					let data = res.datas.find(x => x.time == todaystr) || {};

					this.memberOption.series[0].data.push({
						value: data.cnt || 0,
						name: todaystr
					});
					this.memberOption.xAxis.data.push({
						value: today.format('dd')
					});
				}

				this.memberDom.setOption(this.memberOption);
			},
			async memberMonth() {
				this.memberCutBtn = '月';

				uni.setStorage({
					key: '__memberCutSta' + this.$route.path,
					data: this.memberCutBtn
				});

				this.memberDom.showLoading({
					text: '加载中 · · ·',
					color: '#ff6a6c',
					textColor: '#000',
					maskColor: 'rgba(255, 255, 255, 1)'
				});

				const res1 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id')
					})
					.groupBy('dateToString(add(new Date(0),create_time),"%Y年%m月","+0800") as time')
					.groupField('count(*) as cnt')
					.orderBy('time desc')
					.limit(12)
					.get();

				let res = {
					code: 0,
					datas: []
				};

				await Promise.all([res1]).then(resData => {
					res.datas = resData[0].result.data || [];
				}).catch(err => {
					this.memberDom.hideLoading();
				});

				this.memberDom.hideLoading();

				this.memberOption.xAxis.data = [];
				this.memberOption.series[0].data = [];

				let today;
				let todaystr;
				for (let i = 11; i >= 0; i--) {
					today = new Date();
					today.setDate(1);
					today.setMonth(today.getMonth() - i);
					todaystr = today.format('yyyy年MM月');

					let data = res.datas.find(x => x.time == todaystr) || {};

					this.memberOption.series[0].data.push({
						value: data.cnt || 0,
						name: todaystr
					});
					this.memberOption.xAxis.data.push({
						value: today.format('MM')
					});
				}

				this.memberDom.setOption(this.memberOption);
			},
			memberCharts(callback) {
				this.memberDom = this.$echarts.init(document.getElementById('member'));

				this.memberOption = {
					backgroundColor: '#FFF',
					grid: {
						top: '50px',
						bottom: '60px',
						left: '30px',
						right: '10px'
					},
					tooltip: {
						trigger: 'axis',
						label: {
							show: true
						},
						formatter: function(params) {
							let str = '';

							str += ' ' + params[0].data.name + '   ' + '\n';

							params.forEach(item => {
								str += ' ' + item.seriesName + ': ' + item.data.value;
							});
							return str;
						}
					},
					legend: {
						data: ['新增数'],
						top: '0%',
						textStyle: {
							color: '#000'
						}
					},
					xAxis: {
						axisLine: {
							show: false
						},
						splitLine: {
							show: false
						},
						axisTick: {
							show: true,
							alignWithLabel: true,
							lineStyle: {
								color: '#ccc'
							}
						},
						data: []
					},
					yAxis: {
						axisLine: {
							show: false
						},
						splitLine: {
							show: true,
							lineStyle: {
								color: 'rgba(0, 0, 0, 0.1)'
							}
						},
						axisTick: {
							show: false
						},
						splitArea: {
							show: true,
							areaStyle: {
								color: 'rgba(0, 0, 0, 0)'
							}
						}
					},
					series: [{
						smooth: true,
						name: '新增数',
						type: 'line',
						symbol: 'circle',
						symbolSize: 4,
						showSymbol: false,
						lineStyle: {
							width: 3,
							color: '#ff6a6c',
							shadowColor: 'rgba(255, 106, 108, 0.6)',
							shadowBlur: 10,
							shadowOffsetY: 20
						},
						itemStyle: {
							color: '#ff6a6c'
						},
						data: []
					}]
				};

				window.addEventListener('resize', () => {
					this.memberDom.resize();
				});

				if (typeof callback === 'function') {
					callback();
				}
			},
			async memberDistData() {
				this.memberDistDom.showLoading({
					text: '加载中 · · ·',
					color: '#ff6a6c',
					textColor: '#000',
					maskColor: 'rgba(255, 255, 255, 1)'
				});

				const res1 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id'),
						is_plus: '付费会员'
					})
					.groupBy('all')
					.groupField('count(*) as cnt')
					.get();

				const res2 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id')
					})
					.groupBy('member_gender as gender')
					.groupField('count(*) as cnt')
					.get();

				let fxs = {
					code: 0,
					datas: []
				};

				let gender = {
					code: 0,
					datas: [],
					maps: new Map()
				};

				const resData = await Promise.all([res1, res2]).then(resData => {
					resData[0].result.data.forEach(x => {
						fxs.datas.push({
							cnt: x.cnt,
							is_fxs: '会员'
						});
					});

					resData[1].result.data.forEach(x => {
						switch (x.gender) {
							case 1:
								x.gender = '男';
								break;
							case 2:
								x.gender = '女';
								break;
							default:
								x.gender = '未知';
								break;
						}
						if (gender.maps.has(x.gender)) {
							gender.maps.get(x.gender).cnt += x.cnt;
						} else {
							gender.maps.set(x.gender, {
								cnt: x.cnt,
								gender: x.gender
							});
						}
					});
				}).catch(err => {
					this.memberDistDom.hideLoading();
				});

				this.memberDistDom.hideLoading();

				gender.datas = [...gender.maps.values()];

				if (fxs.datas.length > 0) {
					fxs.code = 200;
				}

				if (fxs.code == 200) {
					fxs.datas.forEach(x => {
						this.memberDistOption.series[0].data.push({
							value: x.cnt,
							name: x.is_fxs
						});
					});
					this.memberDistOption.color.push('#ff6a6c');
				}

				if (gender.datas.length > 0) {
					gender.code = 200;
				}

				if (gender.code == 200) {
					gender.datas.forEach(x => {
						this.memberDistOption.series[1].data.push({
							value: x.cnt,
							name: x.gender
						});

						switch (x.gender) {
							case '男':
								this.memberDistOption.color.push('#2ec7c9');
								break;
							case '女':
								this.memberDistOption.color.push('#c424ff');
								break;
							default:
								this.memberDistOption.color.push('#7e6bff');
								break;
						}
					});
				}
				this.memberDistDom.setOption(this.memberDistOption);
			},
			memberDistCharts(callback) {
				this.memberDistDom = this.$echarts.init(document.getElementById('memberDist'));

				this.memberDistOption = {
					backgroundColor: '#fff',
					color: [],
					tooltip: {
						trigger: 'item',
						formatter: ' {a} \n {b}: {c}   '
					},
					series: [{
							name: '会员',
							type: 'pie',
							radius: ['0', '36%'],
							itemStyle: {
								normal: {
									borderColor: 'rgba(0, 0, 0, 0)'
								}
							},
							label: {
								position: 'inside'
							},
							data: []
						},
						{
							name: '性别分布',
							type: 'pie',
							radius: ['45%', '55%'],
							labelLine: {
								length2: 90,
								lineStyle: {
									color: 'rgba(0, 0, 0, 0.1)'
								}
							},
							label: {
								formatter: params => {
									return '{icon|●}{name|' + params.name + '}{value|' + params.value + '人' +
										'}';
								},
								padding: [0, -70, 16, -70],
								rich: {
									color: '#333',
									icon: {
										fontSize: 16
									},
									name: {
										fontSize: 14,
										padding: [0, 5, 0, 5],
										color: '#666666'
									},
									percent: {
										color: '#333',
										padding: [0, 5, 0, 0]
									},
									value: {
										fontSize: 16,
										color: '#333333'
									}
								}
							},
							data: []
						}
					]
				};

				window.addEventListener('resize', () => {
					this.memberDistDom.resize();
				});

				if (typeof callback === 'function') {
					callback();
				}
			},
			async memberGeoData() {
				this.memberGeoDom.showLoading({
					text: '加载中 · · ·',
					color: '#ff6a6c',
					textColor: '#000',
					maskColor: 'rgba(255, 255, 255, 1)'
				});

				const res1 = this.$db['wmzmall-member']
					.collection()
					.action('base-where-action')
					.where({
						shop_id:uni.getStorageSync('wmzadmin_user_shop_id')
					})
					.groupBy('member_city')
					.groupField('count(*) as cnt')
					.get();

				let res = {
					code: 0,
					datas: []
				};

				await Promise.all([res1]).then(resData => {
					resData[0].result.data.forEach(x => {
						if (!x.member_city) return false;
						let _cnt = x.cnt;
						let _pro = x.member_city.split('-')[1];
						let _data = res.datas.find(d => d.pro == _pro);
						if (_data) {
							_data.cnt += _cnt;
							return false;
						}

						res.datas.push({
							pro: _pro,
							cnt: _cnt
						});
					});
				}).catch(err => {
					this.memberDom.hideLoading();
				})

				this.memberGeoDom.hideLoading();

				this.mapData.forEach(_ => {
					let _pro = res.datas.find(x => x.pro == _.name);
					if (_pro) {
						_.value = _pro.cnt;
					} else {
						_.value = 0;
					}
				});

				this.memberGeoDom.setOption(this.memberGeoOption);
			},
			memberGeoCharts(callback) {
				this.memberGeoDom = this.$echarts.init(document.getElementById('memberGeo'));

				this.mapData = [{
						name: '南海诸岛',
						value: 0
					},
					{
						name: '北京',
						value: 0
					},
					{
						name: '天津',
						value: 0
					},
					{
						name: '上海',
						value: 0
					},
					{
						name: '重庆',
						value: 0
					},
					{
						name: '河北',
						value: 0
					},
					{
						name: '河南',
						value: 0
					},
					{
						name: '云南',
						value: 0
					},
					{
						name: '辽宁',
						value: 0
					},
					{
						name: '黑龙江',
						value: 0
					},
					{
						name: '湖南',
						value: 0
					},
					{
						name: '安徽',
						value: 0
					},
					{
						name: '山东',
						value: 0
					},
					{
						name: '新疆',
						value: 0
					},
					{
						name: '江苏',
						value: 0
					},
					{
						name: '浙江',
						value: 0
					},
					{
						name: '江西',
						value: 0
					},
					{
						name: '湖北',
						value: 0
					},
					{
						name: '广西',
						value: 0
					},
					{
						name: '甘肃',
						value: 0
					},
					{
						name: '山西',
						value: 0
					},
					{
						name: '内蒙古',
						value: 0
					},
					{
						name: '陕西',
						value: 0
					},
					{
						name: '吉林',
						value: 0
					},
					{
						name: '福建',
						value: 0
					},
					{
						name: '贵州',
						value: 0
					},
					{
						name: '广东',
						value: 0
					},
					{
						name: '青海',
						value: 0
					},
					{
						name: '西藏',
						value: 0
					},
					{
						name: '四川',
						value: 0
					},
					{
						name: '宁夏',
						value: 0
					},
					{
						name: '海南',
						value: 0
					},
					{
						name: '台湾',
						value: 0
					},
					{
						name: '香港',
						value: 0
					},
					{
						name: '澳门',
						value: 0
					}
				];

				this.memberGeoOption = {
					tooltip: {
						show: true,
						formatter: function(e) {
							return 0 == e.value ? ' ' + e.name + ': 暂无用户' + '   ' : ' ' + e.seriesName + '   ' +
								'\n' + ' ' + e.name + ': ' + e.value + '   ';
						}
					},
					visualMap: {
						min: 0,
						max: 1000,
						left: 10,
						bottom: 40,
						showLabel: !0,
						text: ['高', '低'],
						pieces: [{
								gt: 200,
								label: '> 200 人',
								color: 'rgba(255, 106, 108, 0.7)'
							},
							{
								gt: 100,
								lte: 200,
								label: '< 200 人',
								color: 'rgba(255, 106, 108, 0.54)'
							},
							{
								gte: 10,
								lte: 100,
								label: '< 100 人',
								color: 'rgba(255, 106, 108, 0.3)'
							},
							{
								gte: 1,
								lt: 10,
								label: '< 10 人',
								color: 'rgba(255, 106, 108, 0.14)'
							},
							{
								value: 0,
								label: '0 人',
								color: 'rgba(255, 106, 108, 0)'
							}
						],
						show: true
					},
					geo: {
						map: 'china',
						roam: !1,
						scaleLimit: {
							min: 1,
							max: 2
						},
						zoom: 1.2,
						top: 60,
						label: {
							show: true
						},
						itemStyle: {
							borderColor: 'rgba(0, 0, 0, 0.24)',
							emphasis: {
								areaColor: 'rgba(255, 106, 108, 1)'
							}
						}
					},
					series: [{
						name: '用户人数',
						type: 'map',
						geoIndex: 0,
						data: this.mapData
					}]
				};

				window.addEventListener('resize', () => {
					this.memberGeoDom.resize();
				});

				if (typeof callback === 'function') {
					callback();
				}
			}
		},
		created() {
			this.getMember();
		},
		mounted() {
			this.memberCharts(() => {
				const memberSta = uni.getStorageSync('__memberCutSta' + this.$route.path) || '日';
				if (memberSta == '日') {
					this.memberDay();
				} else {
					this.memberMonth();
				}
			});

			this.memberDistCharts(() => {
				this.memberDistData();
			});

			this.memberGeoCharts(() => {
				this.memberGeoData();
			});

			this.$nextTick(() => {
				this.$api.scrollOnStorage('uni-page-body', this.$route.path);
			});

			this.$nextTick(() => {
				this.$api.scrollToStorage('uni-page-body', this.$route.path);
			});
		}
	};
</script>

<style>
	.tag {
		margin-top: 30px;
		width: 12%;
		height: 90px;
		background-color: #7d6aff;
		border-radius: 10px;
		margin-right: 2%;
		padding-left: 2%;
		display: flex;
		align-items: center;
		color: #fff;
		cursor: pointer;
		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
	}

	.tag:nth-child(2) {
		background-color: #ffa66a;
	}

	.tag:nth-child(3) {
		background-color: #ff6b6b;
	}

	.tag:nth-child(4) {
		background-color: #69b5ff;
	}

	.tag:nth-child(5) {
		background-color: #b96bff;
	}

	.tag:nth-child(6) {
		background-color: #e9c52b;
	}

	.tag i {
		font-size: 32px;
		margin-right: 14px;
		transition: transform 0.2s;
	}

	.tag_title {
		font-size: 13px;
	}

	.tag_data {
		font-size: 22px;
		font-weight: 400;
	}

	.tag:hover i {
		transform: scale(1.2);
	}

	.area2 {
		height: 500px;
	}

	.area3 {
		height: 600px;
	}
</style>
